using System.Collections.Generic;
using Project.Configs;
using Project.Models;
using Project.Utilities;
using Project.Utilities.Abstractions;
using Project.ViewModels.Abstractions;
using UnityEngine.InputSystem;

namespace Project.ViewModels
{
    public class RootScreenViewModel : DisposableViewModelBase
    {
        private const int AddedPointsToSpendValue = 5;
        private const int AddedHealthPointsValue = 250;
        private const int AddedArmorPointsValue = 50;
        private const int AddedManaPointsValue = 100;

        private readonly InputControls.UIActions _uiActions;
        private readonly List<Character> _characters;
        private readonly ReactiveProperty<bool> _isHelpPanelShown;
        private readonly ReactiveProperty<bool> _isCharacterStatsPanelShown;
        private readonly ReactiveProperty<CharacterStatsPanelViewModel> _characterStatsPanelViewModel;
        private readonly List<CharacterStatsPanelViewModel> _characterStatsPanelViewModels;

        private Character _currentCharacter;

        public RootScreenViewModel(
            InputControls inputControls, 
            IReadOnlyList<Character> characters, 
            IReadOnlyList<CharacterConfig> characterConfigs)
        {
            _uiActions = inputControls.UI;
            _characters = new List<Character>(characters);
            _isHelpPanelShown = new ReactiveProperty<bool>();
            _isCharacterStatsPanelShown = new ReactiveProperty<bool>();
            _characterStatsPanelViewModel = new ReactiveProperty<CharacterStatsPanelViewModel>();
            _characterStatsPanelViewModels = new List<CharacterStatsPanelViewModel>();

            for (int i = 0, length = _characters.Count; i < length; i++)
                _characterStatsPanelViewModels.Add(new CharacterStatsPanelViewModel(_characters[i], characterConfigs[i]));
            _currentCharacter = _characters[0];
            _characterStatsPanelViewModel.Value = _characterStatsPanelViewModels[0];
            
            Subscribe();
        }

        public IReadOnlyReactiveProperty<bool> IsHelpPanelShown => _isHelpPanelShown;
        public IReadOnlyReactiveProperty<bool> IsCharacterStatsPanelShown => _isCharacterStatsPanelShown;
        public IReadOnlyReactiveProperty<CharacterStatsPanelViewModel> CharacterStatsPanelViewModel => 
            _characterStatsPanelViewModel;

        public void ToggleIsHelpPanelShown() => _isHelpPanelShown.Value = !_isHelpPanelShown.Value;

        protected override void Subscribe()
        {
            _uiActions.ShowOrHideHelpPanel.performed += OnShowOrHideHelpPanelActionPerformed;
            _uiActions.ShowOrHideCharacterStatsPanel.performed += OnShowOrHideCharacterStatsPanelActionPerformed;

            _uiActions.SetFirstCharacter.performed += OnSetFirstCharacterActionPerformed;
            _uiActions.SetSecondCharacter.performed += OnSetSecondCharacterActionPerformed;
            _uiActions.SetThirdCharacter.performed += OnSetThirdCharacterActionPerformed;

            _uiActions.AddPointsToSpend.performed += OnAddPointsToSpendActionPerformed;
            _uiActions.AddHealthPoints.performed += OnAddHealthPointsActionPerformed;
            _uiActions.AddArmorPoints.performed += OnAddArmorPointsActionPerformed;
            _uiActions.AddManaPoints.performed += OnAddManaPointsActionPerformed;

            _uiActions.ResetChanges.performed += OnResetChangesActionPerformed;
        }
        protected override void Unsubscribe()
        {
            _uiActions.ShowOrHideHelpPanel.performed -= OnShowOrHideHelpPanelActionPerformed;
            _uiActions.ShowOrHideCharacterStatsPanel.performed -= OnShowOrHideCharacterStatsPanelActionPerformed;

            _uiActions.SetFirstCharacter.performed -= OnSetFirstCharacterActionPerformed;
            _uiActions.SetSecondCharacter.performed -= OnSetSecondCharacterActionPerformed;
            _uiActions.SetThirdCharacter.performed -= OnSetThirdCharacterActionPerformed;

            _uiActions.AddPointsToSpend.performed -= OnAddPointsToSpendActionPerformed;
            _uiActions.AddHealthPoints.performed -= OnAddHealthPointsActionPerformed;
            _uiActions.AddArmorPoints.performed -= OnAddArmorPointsActionPerformed;
            _uiActions.AddManaPoints.performed -= OnAddManaPointsActionPerformed;

            _uiActions.ResetChanges.performed -= OnResetChangesActionPerformed;
        }

        private void ToggleIsCharacterStatsPanelShown() => 
            _isCharacterStatsPanelShown.Value = !_isCharacterStatsPanelShown.Value;

        private void OnShowOrHideHelpPanelActionPerformed(InputAction.CallbackContext context) =>
            ToggleIsHelpPanelShown();
        private void OnShowOrHideCharacterStatsPanelActionPerformed(InputAction.CallbackContext context) =>
            ToggleIsCharacterStatsPanelShown();

        private void OnSetFirstCharacterActionPerformed(InputAction.CallbackContext context) =>
            SetCharacterStatsPanelViewModel(0);
        private void OnSetSecondCharacterActionPerformed(InputAction.CallbackContext context) =>
            SetCharacterStatsPanelViewModel(1);
        private void OnSetThirdCharacterActionPerformed(InputAction.CallbackContext context) =>
            SetCharacterStatsPanelViewModel(2);

        private void OnAddPointsToSpendActionPerformed(InputAction.CallbackContext context) =>
            _currentCharacter.PointsToSpend.Value += AddedPointsToSpendValue;
        private void OnAddHealthPointsActionPerformed(InputAction.CallbackContext context) =>
            _currentCharacter.HealthPoints.Value += AddedHealthPointsValue;
        private void OnAddArmorPointsActionPerformed(InputAction.CallbackContext context) =>
            _currentCharacter.ArmorPoints.Value += AddedArmorPointsValue;
        private void OnAddManaPointsActionPerformed(InputAction.CallbackContext context) =>
            _currentCharacter.ManaPoints.Value += AddedManaPointsValue;

        private void OnResetChangesActionPerformed(InputAction.CallbackContext context) =>
            _currentCharacter.Reset();

        private void SetCharacterStatsPanelViewModel(int index)
        {
            _currentCharacter = _characters[index];
            _isCharacterStatsPanelShown.Value = true;
            _characterStatsPanelViewModel.Value = _characterStatsPanelViewModels[index];
        }
    }
}
